import cx from 'classnames';
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import Button from '../../Button';
import message from '../../Message';
import Modal from '../../Modal';
import TableFilter, { editWidgetConfigs } from '../../TableFilter';
import {
  defaultColumnConfig,
  SELECT_TABLE_MODAL,
  TABLE_ACTION_CELL,
} from '../config';
import TableContext, {
  createContext,
  initTableContext,
  UPDATE_NAME,
} from '../context/table';
import { SvgArrow } from '../Svg';
import { createTableModalParams } from '../utils';
import { ActionColumn as Action, DisplayTable } from './index';

import { prefix } from '../../config';
import { getPrefixCls, isNullOrUndefined } from '../../utils';
import '../style/EditableTable.less';
import * as utils from '../utils';

import type { ModalProps } from '../../Modal';
import type { Context } from '../context/table';
import type {
  AnyObject,
  Column,
  CurOperateInfo,
  DisplayTableProps,
  FilterItem,
  FilterList,
  RowSelection,
} from '../type';

export type ListParams<T extends AnyObject> = { [key in keyof T]?: any };
export interface Props<T extends AnyObject>
  extends ModalProps,
    DisplayTableProps<T> {
  filterList?: FilterList;
  curOperateInfo?: CurOperateInfo<T>;
  onSearch?: (params?: AnyObject) => void;
  onReset?: (params?: AnyObject) => void;
  onConfirm?: (selectedRows: T[]) => void;
  onCancel?: () => void;
}

const prefixCls = getPrefixCls(prefix.editableTable, 'select-table-modal');
function TableModal<T extends AnyObject>(props: Props<T>) {
  const {
    id,
    rowKey,
    visible,
    pagination,
    zIndex,
    style,
    footer,
    getContainer,
  } = props;
  const {
    width = 1000,
    title = '选择数据',
    size = 'middle',
    curOperateInfo = initTableContext.curOperateInfo,
  } = props;
  const { isCanSetting = true, columns = [], dataSource = [], context } = props;
  const modalTableId = `${prefixCls}-modal-table`;

  const { table: tableContextInfo, dispatch } = useContext<Context<T>>(context);
  const ref = useRef<any>();

  const [listParams, setListParams] = useState<AnyObject>({});

  // 本次选择的数据
  const [isShowPopTable, setIsShowPopTable] = useState(false);
  const [selectedRows, setSelectedRows] = useState<T[]>([]);

  const rowSelection = useMemo(() => {
    const { rowSelection } = props;
    if (rowSelection) {
      const onChange = (selectedRows: T[]) => {
        setSelectedRows(selectedRows);
        rowSelection.onChange?.(selectedRows);
      };
      return { ...rowSelection, onChange };
    }
    return rowSelection;
  }, [props.rowSelection]);
  const selectedTableColumns = useMemo(() => {
    let selectCellProps: RowSelection<T>['selectCellProps'];
    if (rowSelection) {
      const { isCanRepeatSelection = true, selectedRows = [] } = rowSelection;
      selectCellProps = !isCanRepeatSelection
        ? (data: T, index: number) => ({
            ...rowSelection.selectCellProps?.(data, index),
            disabled: selectedRows
              .map((item) => item[rowKey])
              .includes(data[rowKey]),
          })
        : rowSelection.selectCellProps;
    }
    const selectedTableColumns: Column<T>[] = [
      ...columns,
      {
        id: TABLE_ACTION_CELL,
        header: '操作',
        meta: { ...defaultColumnConfig[TABLE_ACTION_CELL] },
        cell: (info) => {
          const {
            row: { original: data, index },
          } = info;

          return (
            <Action
              action={['remove']}
              onRemove={() => {
                const disabled =
                  selectCellProps && selectCellProps(data, index).disabled;
                if (disabled) return message.error('此数据禁止删除');
                if (ref.current) {
                  const selectedRows = ref.current.unSelectRow(data);
                  setSelectedRows(selectedRows);
                }
              }}
            />
          );
        },
      },
    ];
    return selectedTableColumns;
  }, [columns, rowSelection]);
  const filterList = useMemo(() => {
    if (!isNullOrUndefined(props.filterList)) return props.filterList;
    return columns.map((column) => {
      const columnMeta = column.meta || {};
      const { dataKey, editType, dataType, editProps } = columnMeta;
      const name = dataKey || column.id;
      const type = editType || dataType;
      const item: FilterItem = {
        name,
        label: column.header as string,
        type: editWidgetConfigs[type] || 'input',
        value: listParams[name],
        props: editProps,
        onChange: (key: string, value: string) =>
          setListParams({ ...listParams, [key]: value }),
      };
      return item;
    });
  }, [props.filterList, columns, listParams]);

  useEffect(() => {
    if (!tableContextInfo.name)
      dispatch({ type: UPDATE_NAME, payload: SELECT_TABLE_MODAL });
  }, [tableContextInfo.name]);
  useEffect(() => {
    if (visible && columns.length) {
      const params = createTableModalParams(columns, curOperateInfo);
      setListParams(params);
    }
  }, [visible, columns, curOperateInfo]);

  const onSearch = (params: AnyObject) => {
    setListParams(params);
    props.onSearch && props.onSearch(params);
  };
  const onReset = (params: AnyObject) => {
    setListParams({});
    props.onReset && props.onReset(params);
  };
  const onChangePagination = (page: number, size: number) => {
    props.onChangePagination &&
      props.onChangePagination(page, size, listParams);
  };
  const onConfirm = () => {
    props.onConfirm?.(selectedRows);
    setSelectedRows([]);
  };
  const onCancel = () => {
    setSelectedRows([]);
    props.onCancel?.();
  };

  const modalProps = { footer, getContainer, visible, title, width, zIndex };
  const defaultTableProps = { isCanResizeColumn: false, isFixedHeight: true };
  const baseTableProps = {
    id,
    size,
    pagination,
    columns,
    dataSource,
    context,
    rowKey,
  };
  const tableProps = {
    ...defaultTableProps,
    ...baseTableProps,
    rowSelection,
    isCanSetting,
  };
  return (
    <Modal
      destroyOnClose
      className={prefixCls}
      {...modalProps}
      style={{ minWidth: 600, maxWidth: 1200, ...style }}
      footer={
        <div className={`${prefixCls}-footer`}>
          {!!rowSelection && (
            <div
              className={`${prefixCls}-footer-text-box`}
              onClick={() => setIsShowPopTable(!isShowPopTable)}
            >
              <span className={`${prefixCls}-footer-text`}>选择的数据</span>
              <span className={`${prefixCls}-footer-text-number`}>
                {selectedRows.length}
              </span>
              <div
                className={cx(`${prefixCls}-footer-text-icon`, {
                  down: isShowPopTable,
                })}
              >
                <SvgArrow />
              </div>
            </div>
          )}

          <Button onClick={onCancel}>取消</Button>
          <Button type="primary" onClick={onConfirm}>
            确定
          </Button>
        </div>
      }
      onOk={onConfirm}
      onCancel={onCancel}
    >
      <div className={`${prefixCls}-content`}>
        <div className={`${prefixCls}-content-table`}>
          {props.children ||
            (filterList && (
              <TableFilter
                list={filterList}
                onSearch={onSearch}
                onReset={onReset}
              />
            ))}
          <div
            id={modalTableId}
            className={modalTableId}
            style={{ height: 584 }}
          >
            <DisplayTable
              {...tableProps}
              ref={ref}
              onChangePagination={onChangePagination}
            />
          </div>
        </div>
        {isShowPopTable && (
          <div className={`${prefixCls}-content-pop`}>
            <div
              className={`${prefixCls}-content-pop-mark`}
              onClick={() => setIsShowPopTable(false)}
            ></div>
            <div className={`${prefixCls}-content-pop-table`}>
              <DisplayTable
                isCanSetting
                rowKey={rowKey}
                columns={selectedTableColumns}
                dataSource={selectedRows}
              />
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}

function TableModalContext<T extends AnyObject>(props: Props<T>) {
  const { context, ...restProps } = props;
  const tableId = useMemo(
    () => props.id || utils.createTableId('table'),
    [props.id],
  );
  const tableContext = useMemo(() => createContext(), [tableId]);
  const tableProps = { ...restProps, id: tableId };
  if (context) {
    return <TableModal {...tableProps} context={context} />;
  } else {
    return (
      <TableContext context={tableContext}>
        <TableModal {...tableProps} context={tableContext} />
      </TableContext>
    );
  }
}
TableModalContext.Filter = TableFilter;
export default TableModalContext;
